package cipher.algorithm;

import java.util.ArrayList;

public abstract class Algorithm {

	private static int KEY_LENGTH;
	private String key;
	private int integer_key;
	
	public Algorithm() {}
	
	public Algorithm(String key) {
		this.key = key;
	}
	
	public static int readBit(int i, int p) { return (i & (1 << p)) >> p; }
	public static int addBitLE(int i, int b) { return (i<<1) | b; }
	public static int write0(int i, int pos){	return (i &= ~(1 << pos));	}
	public static int write1(int i, int pos){	return (i |= (1 << pos));	}
	
	public static long readBit(long i, int p) { return (i & (1 << p)) >> p; }
	public static long addBitLE(long i, int b) { return (i<<1) | b; }
	public static long write0(long i, int pos){	return (i &= ~(1 << pos));	}
	public static long write1(long i, int pos){	return (i |= (1 << pos));	}
	
	public static int stringtoInt32(String suite, int size){
		String str = suite;
		int i, result = 0, len = size;

		if(len > 32)	return -1;
		for(i = len-1; i >= 0; i--){
			switch(str.charAt(i)){
				case '0' : result = write0(result, i); break;
				case '1' : result = write1(result, i); break;
			}
		}
		return result;
	}
	
	public static long stringtoInt64(String suite, int size){
		String str = suite;
		int i, len = size;
		long result = 0;

		if(len > 64)	return -1;
		for(i = len-1; i >= 0; i--){
			switch(str.charAt(i)){
				case '0' : result = write0(result, i); break;
				case '1' : result = write1(result, i); break;
			}
		}
		return result;
	}
	
	public static long stringtoInt(String suite) {
		int size = suite.length();
		long result = 0;

		if(size > 64)
			return -1;
		
		for(int i = size-1; i >= 0; i--)
			switch(suite.charAt(i)){
				case '0' : result = write0(result, i); break;
				case '1' : result = write1(result, i); break;
			}
		
		return result;
	}
	
	public abstract int generateNextNumber();
	public abstract int generateNextNumber(int length);
	
	public abstract ArrayList<String> generateNewKey(int keySize);

	public static int getKEY_LENGTH() { return KEY_LENGTH; }
	public static void setKEY_LENGTH(int bUF_LENGTH) { KEY_LENGTH = bUF_LENGTH; }

	public String getKey() { return key; }
	public void setKey(String key) { this.key = key; }

	public int getInteger_key() { return integer_key; }
	public void setInteger_key(int integer_key) { this.integer_key = integer_key; }
	
}
